﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Furiant.Figment.Items.Lootable;

namespace Furiant.Figment.Agents.Inventory
{
    public interface IInventory : IEnumerable<KeyValuePair<EquipSlotDefinition, IEquippable>>
    {
        /// <summary>
        /// Gets the IHasInventory object whose Inventory property this instance represents.
        /// </summary>
        IHasInventory Owner { get; }

        /// <summary>
        /// Gets the IInventoryOverflowTrap assigned to this instance.
        /// </summary>
        IInventoryOverflowTrap OverflowTrap { get; }
        /// <summary>
        /// Gets the IInventoryUnequipTrap assigned to this instance.
        /// </summary>
        IInventoryUnequipTrap UnequipTrap { get; }

        IEnumerable<EquipSlotDefinition> Keys { get; }
        IEnumerable<IEquippable> Values { get; }
        IEquippable this[EquipSlotDefinition key] { get; }


        /// <summary>
        /// Adds the specified key to the end of the Keys collection.
        /// </summary>
        /// <param name="key">The key to add.</param>
        void AddSlot(EquipSlotDefinition key);

        /// <summary>
        /// Attemps to equip the specified item to the best found map based on the specified key, provided that all 
        /// EquipActionCriteria are satisfied for equipping the item and unequipping any items in overlapping slots.
        /// Any unequipped items are transferred to the UnequipTrap for this instance. Returns whether the 
        /// EquipActionCriteria were satisfied for the respective action(s). Throws an exception if no valid 
        /// EquipSlotMap could be found.
        /// </summary>
        /// <param name="item">The item to equip.</param>
        /// <param name="key">The slot on which to base the search for a valid map.</param>
        /// <returns></returns>
        bool TryEquipItem(IEquippable item, EquipSlotDefinition key);

        /// <summary>
        /// Attempts to unequip the specified item from its active EquipSlotMap, provided that its EquipActionCriteria
        /// are satisfied for the action. Returns false if the EquipActionCriteria were not satisfied. Returns true if
        /// the operation was successful. The unequipped item is transferred to the UnequipTrap for this instance. 
        /// Throws an exception if the specified item is not already equipped.
        /// </summary>
        /// <param name="item">The item to unequip.</param>
        /// <returns></returns>
        bool TryUnequipItem(IEquippable item);

        /// <summary>
        /// Gets the EquipSlotMap to which the specified item is currently equipped. Returns null if the item is not equipped.
        /// </summary>
        /// <param name="item">The equipped item whose active map should be returned.</param>
        /// <returns></returns>
        EquipSlotMap GetItemActiveMap(IEquippable item);

        /// <summary>
        /// Returns an EquipSlotMap from the specified item's EquipSlotMaps collection. The method first attempts to find a 
        /// map whose Primary slot is the specified key. If no such map is found, it will next attempt to find the first map 
        /// whose Referred slots contain the specified slot. Returns null if no valid maps are found.
        /// </summary>
        /// <param name="item">The item for which to find a map.</param>
        /// <param name="key">The slot on which to base the search.</param>
        /// <returns></returns>
        EquipSlotMap GetItemBestMap(IEquippable item, EquipSlotDefinition key);

        /// <summary>
        /// Gets a collection of EquipSlotMap which represents the active maps of any items which are currently equipped
        /// in slots which overlap the specified map.
        /// </summary>
        /// <param name="map">The map whose slots to find in active maps of equipped items.</param>
        /// <returns></returns>
        IEnumerable<EquipSlotMap> GetOverlappingMaps(EquipSlotMap map);

    }
}
